/******************************************************************************
	Cobalt - utility libraries for building XNA games
	Copyright (C) 2008 Philip Djonov

	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2 of the License, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
	for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the
	
		Free Software Foundation, Inc.
		51 Franklin Street, Fifth Floor
		Boston, MA  02110-1301, USA.
******************************************************************************/

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;

namespace Cobalt.Content.Pipeline.Graphics
{
	[ContentImporter( ".mat", DisplayName = "Cobalt Material Importer", DefaultProcessor = "CobaltMaterialProcessor" )]
	public class CobaltMaterialImporter : ContentImporter<CobaltMaterialContent>
	{

		public override CobaltMaterialContent Import( string filename, ContentImporterContext context )
		{
			CobaltMaterialContent ret = new CobaltMaterialContent();
			ret.Identity = new ContentIdentity( filename );
			ret.Name = Path.GetFileNameWithoutExtension( filename );

			MaterialContent propTarget = ret;

			using( ContentTokenReader reader = ContentTokenReader.FromFile( filename ) )
			{
				while( reader.ReadToken( TokenReadFlags.RequireLineStart ) != null )
				{
					switch( reader.LastToken )
					{
					case "inherit":
						if( ret.Parent != null )
							throw new InvalidContentException( "Cannot inherit from more than one material.", reader.LastTokenIdentity );
						ret.Parent = new ExternalReference<CobaltMaterialContent>( reader.ReadRequiredToken(), ret.Identity );
						continue;

					case "layer":
						{
							int layerId;
							switch( reader.ReadRequiredToken( TokenReadFlags.NoLineBreak ) )
							{
								case "depth": layerId = 0; break;
								case "light": layerId = 1; break;

								default:
									throw new InvalidContentException( "Invalid layer ID.", reader.LastTokenIdentity );
							}

							if( ret.Layers.ContainsKey( layerId ) )
								throw new InvalidContentException( "Duplicate layer specified.", reader.LastTokenIdentity );

							string effectName = reader.ReadRequiredToken( TokenReadFlags.NoLineBreak );

							EffectMaterialContent newTarget;
							if( effectName == "null" )
							{
								newTarget = null;
							}
							else
							{
								newTarget = new EffectMaterialContent();

								if( effectName != "inherit" )
									newTarget.Effect = new ExternalReference<EffectContent>( effectName, ret.Identity );
							}

							ret.Layers.Add( layerId, newTarget );
							propTarget = newTarget;
						}
						continue;

					case "tag":
					case "pipeline_tag":
						{
							OpaqueDataDictionary tagTarget = reader.LastToken == "tag" ? ret.Tags : ret.PipelineTags;

							string tagName = reader.ReadRequiredToken( TokenReadFlags.NoLineBreak );
							object value = Helpers.ParsePropertyValue( reader, ret.Identity );

							tagTarget.Add( tagName, value );
						}
						continue;
					}

					//assume the rest are parameters

					if( propTarget == null )
						throw new InvalidContentException( "Parameter definitions may not appear in null layer blocks.", reader.LastTokenIdentity );

					string paramName = reader.LastToken;
					object paramValue = Helpers.ParsePropertyValue( reader, ret.Identity );

					if( paramValue.GetType() == typeof( ExternalReference<TextureContent> ) )
					{
						propTarget.Textures[paramName] = (ExternalReference<TextureContent>)paramValue;
					}
					else
					{
						propTarget.OpaqueData[paramName] = paramValue;
					}
				}
			}

			return ret;
		}
	}
}
